package java21demo;

public class RecordPatterns {

    public static void main(String[] args) {
        String str = "Hello World";

        if (str instanceof String) {
            // do .... use str
        }
        if (str instanceof String s) {
            // do something use s...
        }

        Point point = new Point(42, 24);
        printSum2(point);

        SwitchRecordPatterns switchRecordPatterns = new SwitchRecordPatterns();
        double area = switchRecordPatterns.calcArea(new SwitchRecordPatterns.Circle(new SwitchRecordPatterns.Point(10, 10), 5));
        System.out.println("圆心为(10, 10), 半径为5的圆的面积是: "+ area);

        SwitchRecordPatterns.Rectangle rectangle = new SwitchRecordPatterns.Rectangle(new SwitchRecordPatterns.Point(0, 5), new SwitchRecordPatterns.Point(10, 0));
        double rectangleAre = switchRecordPatterns.calcArea(rectangle);
        System.out.println("矩形左上(0, 5), 右下(10, 0)的面积是: "+ rectangleAre);

    }

    //As of java 16
    record Point(int x, int y) {}


    static void printSum2(Object obj) {
        if (obj instanceof Point(int x, int y)) {
            System.out.println("x+y=" + (x + y));
        }
    }

    //Nested record patterns
    record Rectangle(Point upperLeft, Point lowerRight) {}
    record Circle(Point center, int radius) {}


    static double calcArea(Object obj) {
        if (obj instanceof Rectangle(Point(int x1, int y1), Point(int x2, int y2))) {
            return (x2 - x1) * (y2 - y1);
        } else if (obj instanceof Circle(Point(int x, int y), int r)) {
            //obj instanceof Circle(Point center, int r)  写成这样也可以，因为我们只需要用到参数r
            return Math.PI * r * r;
        }
        return 0.0;
    }

    //type interface
    static double calcAreaTypeInterface(Object obj) {
        if (obj instanceof Rectangle(Point(var x1, var y1), Point(var x2, var y2))) {
            return (x2 - x1) * (y2 - y1);
        } else if (obj instanceof Circle(var center, var r)) {
            return Math.PI * r * r;
        }
        return 0.0;
    }

    static class SwitchRecordPatterns {
        //定义了一个不可变的 Point 类，自动包含：final 字段 x 和 y。 构造函数、equals()、hashCode() 和 toString() 方法
        record Point(int x, int y) {}
        //密封接口. 定义了一个密封接口 Figure，只允许 Rectangle 和 Circle 实现它（通过 permits 指定）
        sealed interface Figure permits Rectangle,Circle {}
        record Rectangle(Point upperLeft, Point lowerRight) implements Figure {}
        record Circle(Point center, int radius) implements Figure {}

        /**
         * 计算图形面积
         * @param obj
         * @return
         */
        double calcArea(Figure obj) {
            // switch表达式匹配Figure类型。 由于 Figure 是密封接口，编译器知道所有可能的子类，可以验证 switch 是否覆盖所有情况
            // 模式匹配： 可以直接在 case 中解构Record类
            return switch (obj) {
                //如果obj是null,返回0.0
                case null -> 0.0;
                //如果是 Rectangle，解构出两个 Point，使用了嵌套解构，再进一步解构出坐标，计算矩形面积
                case Rectangle(Point(var x1, var y1), Point(var x2, var y2)) -> (x2 - x1) * (y2 - y1);
                //如果是 Circle，解构出圆心和半径，计算圆面积
                case Circle(var center, var radius) -> Math.PI * radius * radius;
            };
        }
    }
}
